using System;
using System.Collections;

namespace RomanJendrusz.Amazon.ETL.Infrastructure.IoC
{
    /// <summary>
    /// Represents the contract of an Inversion Of Control Container
    /// </summary>
    public interface IDependencyResolver
    {
        /// <summary>
        /// Resolves this instance.
        /// </summary>
        /// <typeparam name="Dependency">The type of the Dependency.</typeparam>
        /// <returns></returns>
        Dependency Resolve<Dependency>();

        /// <summary>
        /// Resolves the specified key.
        /// </summary>
        /// <typeparam name="Dependency">The type of the Dependency.</typeparam>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        Dependency Resolve<Dependency>(string key);

        /// <summary>
        /// Adds the component.
        /// </summary>
        /// <typeparam name="OfType">The type of class.</typeparam>
        void AddComponent<OfType>();

        /// <summary>
        /// Adds the component.
        /// </summary>
        /// <typeparam name="OfType">The type of class.</typeparam>
        /// <param name="key">The key.</param>
        void AddComponent<OfType>(string key);

        /// <summary>
        /// Adds the component.
        /// </summary>
        /// <typeparam name="Service">The type of the service.</typeparam>
        /// <typeparam name="Implementation">The type of the implementation.</typeparam>
        void AddComponent<Service, Implementation>() where Implementation : class;

        /// <summary>
        /// Adds the component.
        /// </summary>
        /// <typeparam name="Service">The type of the service.</typeparam>
        /// <typeparam name="Implementation">The type of the implementation.</typeparam>
        /// <param name="key">The key.</param>
        void AddComponent<Service, Implementation>(string key) where Implementation: class ;

        /// <summary>
        /// Adds the component.
        /// </summary>
        /// <typeparam name="OfType">The type of the class.</typeparam>
        /// <param name="lifestyle">The lifestyle.</param>
        void AddComponent<OfType>(LifeStyle lifestyle);


        /// <summary>
        /// Adds the component.
        /// </summary>
        /// <typeparam name="OfType">The type of the class.</typeparam>
        /// <param name="key">The key.</param>
        /// <param name="lifestyle">The lifestyle.</param>
        void AddComponent<OfType>(string key, LifeStyle lifestyle);

        /// <summary>
        /// Adds the component.
        /// </summary>
        /// <typeparam name="Service">The type of the service.</typeparam>
        /// <typeparam name="Implementation">The type of the implementation.</typeparam>
        /// <param name="lifestyle">The lifestyle.</param>
        void AddComponent<Service, Implementation>(LifeStyle lifestyle) where Implementation : class;

        /// <summary>
        /// Adds the component.
        /// </summary>
        /// <typeparam name="Service">The type of the service.</typeparam>
        /// <typeparam name="Implementation">The type of the implementation.</typeparam>
        /// <param name="key">The key.</param>
        /// <param name="lifestyle">The lifestyle.</param>
        void AddComponent<Service, Implementation>(string key, LifeStyle lifestyle) where Implementation : class;


        /// <summary>
        /// Adds the instance.
        /// </summary>
        /// <typeparam name="Type">The type of the injected instance.</typeparam>
        /// <param name="injectedInstance">The injected instance.</param>
        void AddInstance<Type>(Type injectedInstance);

        /// <summary>
        /// Adds the instance.
        /// </summary>
        /// <typeparam name="Type">The type of the injected instance.</typeparam>
        /// <param name="key">The key.</param>
        /// <param name="injectedInstance">The injected instance.</param>
        void AddInstance<Type>(string key, Type injectedInstance);

        void AddComponent<Service, Implementation>(IDictionary parameters) where Implementation:class;

        /// <summary>
        /// Resolves the specified type of object with arguments.
        /// </summary>
        /// <typeparam name="Dependency">The type of the dependency.</typeparam>
        /// <param name="arguments">The arguments.</param>
        /// <returns></returns>
        Dependency Resolve<Dependency>(IDictionary arguments);

        /// <summary>
        /// Resolves the specified service.
        /// </summary>
        /// <param name="service">The service.</param>
        /// <returns></returns>
        Object Resolve(Type service);
    }
}